package quota

import (
	"context"
	"fmt"
	"os"
	"sync"
	"time"

	"go-common/library/net/rpc/warden"
	"go-common/library/net/rpc/warden/resolver"
	"go-common/library/net/rpc/warden/resolver/direct"
	"go-common/library/rate/limit/quota/api"
	xtime "go-common/library/time"

	"go-common/library/sync/errgroup.v2"
)

var (
	once          sync.Once
	defaultClient api.QuotaClient
)

// Init init client
func Init() {
	once.Do(func() {
		if defaultClient != nil {
			return
		}
		resolver.Register(direct.New())
		directCall = directWardenCall
		var err error
		defaultClient, err = api.NewClient(&warden.ClientConfig{
			Dial:              xtime.Duration(time.Second * 10),
			Timeout:           xtime.Duration(time.Millisecond * 250),
			Subset:            50,
			KeepAliveInterval: xtime.Duration(time.Second * 60),
			KeepAliveTimeout:  xtime.Duration(time.Second * 20),
			NonBlock:          true,
		})
		if err != nil {
			panic(fmt.Sprintf("quota server init client failed err: %v", err))
		}
	})
	return
}

func clientAddr() string {
	name := os.Getenv("POD_NAME")
	if name != "" {
		return name
	}
	var err error
	if name, err = os.Hostname(); err != nil {
		panic(fmt.Sprintf("can't get hostname: %v", err))
	}
	return fmt.Sprintf("%s:%d", name, os.Getpid())
}

func Close() {
	eg := errgroup.Group{}
	allowerLock.Lock()
	for key, r := range allowers {
		if r != nil {
			r := r
			eg.Go(func(ctx context.Context) error {
				r.Close()
				return nil
			})
			delete(allowers, key)
		}
	}
	allowerLock.Unlock()
	waiterLock.Lock()
	for key, r := range waiters {
		if r != nil {
			r := r
			eg.Go(func(ctx context.Context) error {
				r.Close()
				return nil
			})
			delete(waiters, key)
		}
	}
	waiterLock.Unlock()
	_ = eg.Wait()
	return
}
